package util;


/**
 * The Stemmer class encapsulates both Portuguese, Spanish and English stemmers.
 * A string sent by parameter will be tested over these three stemmers. If the 
 * content is modified by one of these stemmers the new stemmed string is returned.
 * <p>
 * <pre>
* import static org.junit.Assert.assertEquals;
* 
* import org.junit.Test;
* 
* public class StemmerTest {
* 
*   private String text = "A importância do processo e das formas de organização " +
*     "do conhecimento está associada à consciência dos cientistas sobre o " +
*     "papel que exercem a informação e a tecnologia no contexto produtivo " +
*     "contemporâneo. Nele a importância crescente do conhecimento associa-se " +
*     "à sua capacidade de responder às necessidades sociais.";
* 
*   private String expectedText = "importânc process form organiz conhec assoc consciênc " +
*     "cientist papel exerc inform tecnolog context produt contemporâneo. " +
*     "importânc crescent conhec associa-s capac respond necess sociais.";
* 
*   private String word = "importância";
*   private String expectedWord = "importânc";
* 
*   &#64;Test
*   public void mstem() throws Exception  {
*     String output = Stemmer.mstem(text);
*     System.out.println(output.toString());
*     assertEquals(output.toString(), expectedText); 
*   }
* 
*   &#64;Test
*   public void stem() throws Exception  {
*     String output = Stemmer.stem(word);
*     System.out.println(output.toString());
*     assertEquals(output.toString(), expectedWord); 
*   }
* }
 * </pre>
 */

public class Stemmer {

	/**
	 * English stemmer.
	 * @param word input paramenter.
	 * @return the word modified.
	 * @throws Exception
	 */
	private static String enstemming(String word) throws Exception {
		EnglishStemmer stem = new EnglishStemmer();
		char[] ch = word.toLowerCase().toCharArray();
		for (int i = 0; i < ch.length; i++) {
			stem.add(ch[i]);
		}
		stem.stem();
		return stem.toString();
	}
	
	/**
	 * Portuguese stemmer.
	 * @param word input paramenter.
	 * @return the word modified  
	 * @throws Exception
	 */
	private static String ptstemming(String word) throws Exception {
		PortugueseStemmer stem = new PortugueseStemmer();
		return stem.stem(word);
	}
	
	/**
	 * Spanish stemmer.
	 * @param word input parameter.
	 * @return the word modified.
	 * @throws Exception
	 */
	private static String spstemming(String word) throws Exception {
		SpanishStemmer stem = new SpanishStemmer();
		return stem.stem(word);
	}

	/**
	 * The method receives a term and applies both Portuguese, Spanish and
	 * English stemmer. If one of these stemmers change the term it will be 
	 * returned, otherwise the original term. 
	 * @param term input parameter.
	 * @return Returns the stem.
	 * @throws Exception
	 */
	public static String stem(String term) throws Exception {
		String stem = "", stemAux = "";;
		stem = ptstemming(term); //Starts with Portuguese
		stemAux = stem;
		// Spanish
		stem = spstemming(term);
		if (stem.length() <= stemAux.length())
			stemAux = stem;
		// English
		stem = enstemming(term);
		if (stem.length() <= stemAux.length())
			stemAux = stem;
		return stemAux.toLowerCase();
	}
	
	
	/**
	 * Returns the stem for string with multiple tokens wiping out stop words.
	 * @param term input parameter.
	 * @return Returns the stem.
	 * @throws Exception
	 */
	public static String mstem(String term) throws Exception {
		String[] terms = term.split(" ");
		StringBuffer result = new StringBuffer();
		for (int idx=0; idx < terms.length; idx++) {
			if (!Util.isStopWord(terms[idx].toLowerCase())) {
				result.append(" "+stem(terms[idx]));
			}
		}
		if (result.toString().equalsIgnoreCase(""))
			return term;
		return result.toString().trim();
	}

}
